package com.arrogames.blondbattle.game.combat 
{
	import ash.core.Entity;
	import ash.tools.ListIteratingSystem;
	import com.arrogames.blondbattle.game.combat.Damage;
	import com.arrogames.blondbattle.game.movement.Dimension;
	import com.arrogames.blondbattle.game.rendering.Display;
	import com.arrogames.blondbattle.game.combat.Health;
	import com.arrogames.blondbattle.game.movement.Position;
	import com.arrogames.blondbattle.game.combat.Reload;
	import com.arrogames.blondbattle.game.movement.Speed;
	import com.arrogames.blondbattle.game.EntityCreator;
	import com.arrogames.blondbattle.game.combat.CombatNode;
	import flash.geom.Point;
	
	import org.as3commons.logging.api.ILogger;
	import org.as3commons.logging.api.getLogger;
	
	/**
	 * ...
	 * @author ...
	 */
	public class CombatSystem extends ListIteratingSystem 
	{
		
		private static const logger:ILogger = getLogger(CombatSystem);
		private var entityCreator:EntityCreator = null;
		
		public function CombatSystem(creator:EntityCreator) 
		{
			entityCreator = creator;
			super(CombatNode, updateNode, nodeAdded, nodeRemoved);
		}
		
		private function nodeAdded(node:CombatNode):void {
			node.motion.stop();
		}
		
		public function nodeRemoved(node:CombatNode):void {
			node.motion.move();
		}
		
		private function updateNode(currentNode:CombatNode, time:Number) : void {
			var targetEntity:Entity = currentNode.target.node.entity;
			var targetDimension:Dimension = currentNode.target.node.dimension;
			var targetFaction:Faction = currentNode.target.node.faction;
			var currentEntity:Entity = currentNode.entity;
			var currentDimension:Dimension = currentNode.dimension;
			
			var reload:Reload = currentNode.weapon.reload;
			var damage:Damage = currentNode.weapon.damage;
			var speed:Speed = currentNode.weapon.speed;
			var range:Range = currentNode.weapon.range;
			
			reload.value = reload.value - time;
			if (reload.reloaded()) {
				reload.reset();
				logger.debug("unit " + currentEntity.name + " has reloaded, firing missile at " + targetEntity.name);
				var currentPosition:Position = currentEntity.get(Position);
				var targetPosition:Position = targetEntity.get(Position);
				var currentEntityHeight:Number = currentDimension.height;
				var targetEntityHeight:Number = targetDimension.height;
				var speedPoint:Point = createSpeedVariables(currentPosition, targetPosition, currentEntityHeight, targetEntityHeight, speed);
				//create the missile
				entityCreator.createMissile(
					currentPosition.position.x,
					currentPosition.position.y - currentEntityHeight/2,
					speedPoint.x,
					speedPoint.y,
					0,
					damage.value,
					range.value,
					targetFaction.getOtherFaction()
				);
			}
		}
		
		/**
		 * Check the variables for the x and y speed required for the missile to hit the target in the center
		 * 
		 * @param	currentPosition
		 * @param	targetPosition
		 * @param	currentEntityHeight
		 * @param	targetEntityHeight
		 * @param	speed
		 * @return	Point with the x and y speeds
		 */
		private function createSpeedVariables(currentPosition:Position, targetPosition:Position, currentEntityHeight:Number, targetEntityHeight:Number, speed:Speed) : Point
		{
			//calculate the differences in x and y coordinates
			var diffX:Number = targetPosition.position.x - currentPosition.position.x;
			var targetCenter:Number = (targetPosition.position.y - targetEntityHeight / 2);
			var currentCenter:Number = (currentPosition.position.y - currentEntityHeight / 2 );
			var diffY:Number =  targetCenter - currentCenter;
			
			var xSpeed:Number = speed.value;
			//check if the speed for the x axis needs to be inverted due to the target being to the left of the shooter
			if (diffX < 0) {
				xSpeed = -speed.value;
			}
			//the y speed can be calculated based on the relative difference between the xSpeed and the x difference (the distance to the target)
			var ySpeed:Number = diffY * xSpeed / diffX;
			// if the target is below the shooter and the speed is not negative, make it so
			if ( diffY < 0 && ySpeed > 0) {
				ySpeed = -ySpeed;
			}
			return new Point(xSpeed, ySpeed);
		}
		
	}

}